package com.example.http.demo.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.TimeZone;

public class JsonUtil {


    private static final Logger LOGGER = LoggerFactory.getLogger(JsonUtil.class);

    private JsonUtil() {

    }

    public static final ObjectMapper OBJECT_MAPPER;

    static {
        OBJECT_MAPPER = new ObjectMapper();
        //反序列化的时候如果多了其它属性，不抛出异常
        OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        //如果是空对象的时候，不抛异常
        OBJECT_MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        // 接受单个字符的值反序列化为数组
        OBJECT_MAPPER.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
        // 没有匹配的属性名称时不作失败处理
        OBJECT_MAPPER.configure(MapperFeature.AUTO_DETECT_FIELDS, true);
        //取消时间的转换格式，默认是时间戳，同时需设置时间格式
        OBJECT_MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        //设置日期格式化方式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT+8"));
        OBJECT_MAPPER.setDateFormat(dateFormat);
    }

    /**
     * obj to T
     *
     * @param obj   cache key
     * @param clazz 返回class
     * @param <T>   返回类型
     * @return 实体
     */
    public static <T> T parseObject(Object obj, Class<T> clazz) {
        return obj != null ? parseObject(obj2String(obj), clazz) : null;
    }

    /**
     * s to t
     *
     * @param s
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T parseObject(String s, Class<T> clazz) {
        try {
            return StringUtils.isEmpty(s) ? null : OBJECT_MAPPER.readValue(s, clazz);
        } catch (Exception e) {
            LOGGER.error("object mapper parse object error ", e);
            return null;
        }
    }

    /**
     * o to t
     *
     * @param o
     * @param type
     * @param <T>
     * @return
     */
    public static <T> T parseObject(Object o, TypeReference<T> type) {
        try {
            return o != null ? OBJECT_MAPPER.readValue(obj2String(o), type) : null;
        } catch (Exception e) {
            LOGGER.error("object parse type error", e);
            return null;
        }
    }

    /**
     * s to T
     *
     * @param s
     * @param type
     * @param <T>
     * @return
     */
    public static <T> T parseObject(String s, TypeReference<T> type) {
        try {
            return OBJECT_MAPPER.readValue(s, type);
        } catch (Exception e) {
            LOGGER.error("string parse object error ", e);
            return null;
        }
    }

    /**
     * obj 2 string
     *
     * @param obj
     * @return
     */
    public static String obj2String(Object obj) {
        try {
            return OBJECT_MAPPER.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            LOGGER.error("object parse string error ", e);
            return null;
        }
    }


}


